package com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.sql;


import com.alibaba.druid.sql.SQLUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.parse.Parser;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.tree.ParseTree;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.utils.CaterFileUtil;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.xmind.build.BuildJson;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.xmind.build.BuildXmind;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.xmind.build.BuildXmindTree;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.life.BaseNodeBuilder;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.life.ElementBuilder;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.tree.TreeNode;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.xmind.SaveType;
import lombok.Data;
import org.xmind.core.CoreException;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//解析时的上下文
@Data
public class AppContent {

    //上下文名称
    private String name;

   //读取的文件地址
   private String path;

   //读取文件后的信息
    private List<String> stringList = new ArrayList<>();

   //基础节点信息
    private List<BaseNode> baseNodeList = new ArrayList<>();

    //加载后的节点信息
    private Map<String,Element> elementMap = new HashMap<>();

    //解析后的节点信息
    private List<Element> resElements = new ArrayList<>();

    //完全解析后的SQL语句
    private String sql;

    //信息来源类型
    private InputType inputType;


    public AppContent Start() throws IOException {
        List<String> stringList = CaterFileUtil.readFileLine(path);
        this.inputType = InputType.JSON;
        if(!stringList.isEmpty()){
            //处理读取的信息

            this.stringList = stringList;

            //加载节点列表
            BaseNodeBuilder baseNodeBuilder = BaseNodeBuilder.add(stringList).build();



            if(!baseNodeBuilder.getBaseNodeList().isEmpty()){

               //构建元素
                buildElementList(baseNodeBuilder);
            }

        }
        return this;
    }


    public void buildElementList(BaseNodeBuilder baseNodeBuilder) throws IOException {
        //基础节点列表
        this.setBaseNodeList(baseNodeBuilder.getBaseNodeList());

        //加载元素列表
        ElementBuilder elementBuilder = ElementBuilder.add(baseNodeBuilder).build();
        List<Element> elementList = elementBuilder.getElementList();


        //赋值上下文,未处理的元素
        this.setResElements(elementList);

        if(!elementList.isEmpty()){
            //节点解析出节点SQL
            Parser sqlNodeParse = Parser.add(elementList).parse();

            //设置最终的元素map
            this.setElementMap(sqlNodeParse.getElementMap());

            //解析出结果
            List<Element> resElements = sqlNodeParse.getElements();


            //设置结果元素列表
            this.resElements = resElements;

        }
    }

    //构造最终的SQL语句
    public AppContent buildSql(){
        if(!resElements.isEmpty()){
            for(Element element :resElements){
                if(element.getName().equals("run")){
                    this.sql = element.getBuildSql();
                    break;
                }
            }

        }

        return  this;
    }


    //输出到文件
    public void out(Boolean isCheck, SaveType[] saveTypes) throws IOException, CoreException, NoSuchFieldException, ClassNotFoundException, InstantiationException, IllegalAccessException {

        //构建SQL
        this.buildSql();


        //构建文件对象
        File file = new File(path);

        //获取文件名称
        String[] fileNames = file.getName().split("json");

        String fileName = fileNames[0].substring(0,fileNames[0].length()-1)+"--build";

        //构造输出文件夹
        String outPath = file.getParentFile().getPath()+"/"+fileName+"/";

        //如果没有文件夹的话需要创建
        File dir =new  File(outPath);
        if(!dir.exists()){
            dir.mkdir();
        }


        if(sql!=""){
            List<String> list = new ArrayList<>();
            sql =   SQLUtils.formatMySql(sql);
            list.add(sql);
            if(isCheck){
                //测试sql执行
//                if(TestSql.testSql(sql)){
//                    CaterFileUtil.writeFileLine(list,outPath+fileName+".sql");
//                }
            }else {
                CaterFileUtil.writeFileLine(list,outPath+fileName+".sql");
            }


            //构造调用树
            ParseTree parseTree = ParseTree.add(this).build();

            //获取调用树
            TreeNode mainNode = parseTree.getMainNode();

            //转为字符串
            ObjectMapper objectMapper = new ObjectMapper();
            String treeStr = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mainNode);



            if(treeStr!=null&&treeStr!=""){


                //进行保存
                if(saveTypes.length!=0){

                    for (SaveType saveType : saveTypes){

                        if(saveType==SaveType.XMIND){
                            String xmindOutPath = outPath+fileName+".xmind";
                            BuildXmind.build(this,xmindOutPath);
                        }

                        if(saveType == SaveType.XMINDTREE){
                            String xmindTreeOutPath = outPath+fileName+".tree.xmind";

                            //构建思维导图
                            BuildXmindTree.add(xmindTreeOutPath,mainNode).save(saveTypes);
                        }

                        if(saveType == SaveType.JSON){
                            //获取到可阅读json
                            String json = BuildJson.build(this);
                            String jsonOutPath = outPath+fileName+".json";
                            CaterFileUtil.writeStr(json,jsonOutPath);
                        }

                        if(saveType == SaveType.JSONTREE){
                            //设置写入的文件

                            String jsonOutPath = outPath+fileName+".tree.json";
                            //写入文件
                            CaterFileUtil.write(treeStr,jsonOutPath);
                        }

                        if (saveType == SaveType.EXECTREE){
                            //写入执行树
                            String execTreeOutPath = outPath+fileName+".tree.json";
                            com.xymtop.sqlcater.core.sql.sqlparser.toobj.parse.Parser.Parser(this).parse().out(execTreeOutPath);

                        }


                    }

                }

            }

        }

    }
}
